package code.whmmm.util.http;

import code.whmmm.util.http.pojo.TrustSslManager;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import code.whmmm.util.http.entity.HttpReq;
import code.whmmm.util.http.impl.DefaultHandler;

import java.util.Map;

/**
 * <p><b>
 * http 执行 门面,通过 execute 执行
 * </b></p>
 * <br/>
 *
 * @author Zero
 * @date 2019/8/1 1:35
 */
public class HttpFacade {

    private HttpFacade() {

    }

    private static String POST = "post";
    private static final Logger LOGGER = LoggerFactory.getLogger(HttpFacade.class);


    /**
     * 获取 HttpUriRequest
     *
     * @param method         get | post (目前只支持 post | get ，后续会增加)
     * @param url            请求地址
     * @param config         请求配置
     * @param requestHandler 请求参数处理 对象
     * @param param          请求参数
     * @return HttpUriRequest
     */
    private static HttpUriRequest getUriRequest(String method,
                                                String url,
                                                RequestConfig config,
                                                RequestHandler requestHandler,
                                                Map<String, Object> param,
                                                String contentType) {
        HttpUriRequest req = null;
        try {
            if (POST.equalsIgnoreCase(method)) {
                // post 方式
                HttpPost post = new HttpPost(url);
                post.setConfig(config);
                if (requestHandler == null) {
                    requestHandler =
                            DefaultHandler.DEFAULT_JSON_REQ_HANDLER;
                }

                String s = requestHandler.process(param);

                StringEntity entity = new StringEntity(
                        s
                );

                String content = "application/json;charset=utf-8";
                if (contentType != null && !"".equals(contentType)) {
                    content = contentType;
                }
                entity.setContentType(content);

                post.setEntity(entity);
                req = post;

            } else {
                // get 方式
                URIBuilder builder = new URIBuilder(url);
                if (param != null) {
                    for (String it : param.keySet()) {
                        String v = "";
                        Object o = param.get(it);
                        if (o != null) {
                            v = o.toString().trim();
                        }
                        builder.addParameter(it.trim(), v);
                    }
                }

                req = new HttpGet(builder.build());
            }
        } catch (Exception e) {
            LOGGER.error(e.getMessage(), e);
        }
        return req;
    }

    private static <T> HttpUriRequest createUriRequest(HttpReq<T> req, RequestConfig config) {
        HttpUriRequest request = getUriRequest(req.getHttpMethod(),
                req.getUrl(),
                config,
                req.getReqHandler(),
                req.getParam(),
                req.getContentType());

        String s1;
        String s2;
        Map<String, String> header = req.getHeader();
        if (header != null) {
            for (String k : header.keySet()) {
                request.addHeader(k, header.get(k));
            }
        }
        return request;
    }

    private static CloseableHttpClient createClient(HttpReq req) {
        CloseableHttpClient client;
        if (req.isIgnoreSsl()) {

            client = HttpClientBuilder.create().setSSLSocketFactory(
                    TrustSslManager.getSslFactory()
            ).build();

            if (client == null) {
                LOGGER.error("创建 http client 失败！！！");
                return null;
            }

        } else {
            client = HttpClientBuilder.create().build();
        }
        return client;
    }


    /**
     * 执行请求
     * <pre>
     *     {@code
     *
     *     use example:
     *         HttpReq <String> req = null;
     *         // 下面是 3 中 不同的 HttpReq
     *         // 执行 后 返回 string
     *         req = HttpReqFactory.createDefault();
     *
     *         // 执行后 返回 map<string,object>
     *         req = HttpReqFactory.createMapReq("url",paramMap,'get'|'post');
     *
     *         // 执行后返回 List<Map<String,Object>
     *         req = HttpReqFactory.createListReq("url",paramMap,'get'|'post');
     *
     *         HttpFacade.execute(req);
     *
     *     }
     * </pre>
     *
     * @param req 使用 {@code HttpReq.create() 或 HttpReq.createDefault()} 创建
     * @param <T> 返回值类型
     * @return T
     */
    public static <T> T execute(HttpReq<T> req) {


        // 响应结果 字符串
        String resultString;
        T t = null;
        try {
            if (req.getRespHandler() == null) {
                throw new RuntimeException("参数 responseHandler 不能为空!!!");
            }
            RequestConfig config = RequestConfig.copy(RequestConfig.DEFAULT).build();

            HttpUriRequest request = createUriRequest(req, config);

            if (request == null) {
                throw new RuntimeException("创建 请求失败！！！");
            }

            CloseableHttpClient client = createClient(req);
            if (client == null) {
                throw new RuntimeException("创建 HttpClient 请求失败！！！");
            }

            CloseableHttpResponse response = client.execute(request);

            if (response != null) {
                resultString = EntityUtils.toString(response.getEntity());

                try {
                    t = req.getRespHandler().process(resultString);
                } catch (Exception e) {
                    LOGGER.error(e.getMessage(), e);
                }

                // 关闭 response 释放 response
                response.close();
            }

            // 关闭 client ,释放资源
            client.close();

        } catch (Exception e) {
            LOGGER.error(e.getMessage(), e);
        }
        return t;
    }


}
